Skip to content

fix: wipe secrets on every exit of softsign keygen, softsign import and yubihsm setup - #15

Merged
aeddi merged 18 commits into
mainfrom
wipe-secrets-on-every-command-exit
Nov 4, 2026
Merged

aeddi merged 18 commits into
mainfrom
wipe-secrets-on-every-command-exit

Conversation

@aeddi

@aeddi aeddi commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Three commands ended the process with process::exit while key material was in memory, and
process::exit runs no destructors, so the key was never wiped. This is the fix #14
made for yubihsm keys import, applied to them:

  • softsign keygen and softsign import exit on a failed write only once the key is dropped.
    Import also keeps the secp256k1 bytes it writes in a buffer that wipes itself.
  • yubihsm setup returns why it stopped, and exits only after the admin mnemonic, the role
    passwords and the wrap key have been dropped. That covers a declined erase, an undecodable
    mnemonic and an HSM error. --print-only no longer calls exit(0).
  • Setup reads its HSM credentials once, before deriving anything. With a password_file, it
    read the file again at the erase step, where a failed read ended the process with every
    secret held.
  • Setup's working copies of secrets wipe themselves, including on a panic: the typed
    mnemonic, the words it prints, and the entropy it derives the mnemonic from.

Exit codes and messages are unchanged. FORK.md row 14 now covers key import and setup, and
its note names what stays in memory anyway: the copies yubihsm keeps of every key setup
installs, and the standard library's stdin and stdout buffers.

It also fixes a flaky test: a TCP test listens for its KMS on a port the OS assigns, and a UNIX
test KMS keeps its socket in its own directory under /tmp. Test builds now have no warnings with any
backend alone.

Changes

  • Pin what each command prints and returns, before the fixes — 4cbd624, 4b012c7
  • Wipe the key before softsign keygen and softsign import exit on a failed write — 0a98cb9, cac6f7d
  • Exit yubihsm setup only after its secrets are dropped — 7f6b8f3
  • Read setup's credentials before deriving any secret — ed35a69
  • Wipe the mnemonic typed into setup, which makes setup's mnemonic reader public for the test — bf5356e
  • Keep setup's working secrets in buffers that wipe themselves — ef91566
  • Pin setup's random mnemonic, its HSM failure report and import's refusal of the Base64 format — 22faab3, d565c70
  • Say setup can stop after erasing the HSM — 8e740b9
  • Give each test KMS a port and socket nothing else can hold, and drop the unused rand dev-dependency — 8ab6d0a, 4a6e71f
  • Build each CLI test helper only where it is used — 522ce0a
  • Update FORK.md row 14, its note and the verification counts — 159b1d8, a347687, be1865d, 9525dd4

Testing

  • CLI tests pin the exit code and every line they can predict of softsign keygen,
    softsign import and yubihsm setup (on MockHsm, typing the mnemonic and the answer). The
    ones added first passed before the fixes, and all pass after.
  • Unit tests show that a failed key write and setup's two stdin readers come back to run():
    one that exits in place kills the test process.
  • A test deletes setup's password file while setup waits for the confirmation. Setup still
    finishes; before the fix it exited with "couldn't read key from".
  • The test binary whose allocator scans freed memory finds no typed mnemonic after setup reads
    one. Before the fix it found it.
  • No test makes the erase itself fail: it reconnects with the credentials the first
    connection just used, which MockHsm accepts. That path changes only mechanically.
  • 75 unit + 40 integration tests pass on stable and 1.85, printing nothing but their results.
    Test builds have no warnings with yubihsm, yubihsm-server, softsign, ledger or
    fortanixdsm alone.

@aeddi
aeddi merged commit 7598b46 into main Nov 4, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant